// Dart 3.0 或更高版本支持 Extension Types 和 Records

// --- 1. 基本定义与用法 (IdNumber 示例) ---
extension type IdNumber(int id) {
  // 包装（并可能改变）底层 int 类型的 '<' 操作符
  // 注意：参数类型也是 IdNumber
  operator <(IdNumber other) => id < other.id;

  // 没有声明 '+' 操作符，因为 ID 号不应该做加法
  // int operator +(int other) => id + other; // 如果允许，可以这样写
}

void main_idNumberExample() {
  print('--- 1. 演示基本扩展类型 (IdNumber) ---');
  // 没有扩展类型约束时，int 可以进行不安全的操作
  int myUnsafeId = 42424242;
  myUnsafeId = myUnsafeId + 10; // 对于 ID 来说，这通常不合理，但 int 允许
  print('不安全的 ID 操作: $myUnsafeId');

  var safeId = IdNumber(42424242);
  print('安全的 ID (扩展类型): ${safeId.id}'); // 通过 .id 访问底层 int 值

  // safeId + 10; // 编译时错误: IdNumber 没有定义 '+' 操作符。
  print('尝试 safeId + 10; --> 编译时错误 (已注释)');

  // myUnsafeId = safeId; // 编译时错误: 不能将 IdNumber 赋给 int。类型不匹配。
  print('尝试 myUnsafeId = safeId; --> 编译时错误 (已注释)');

  // 需要显式转换回其表示类型 int
  myUnsafeId = safeId as int; // OK: 运行时强制类型转换 (不推荐，破坏了抽象)
  // 或者更安全地访问底层值
  myUnsafeId = safeId.id; // OK: 通过表示名访问底层值
  print('将 safeId 转换回 int: $myUnsafeId');

  bool comparison = safeId < IdNumber(42424241); // OK: 使用 IdNumber 定义的 '<' 操作符
  print('safeId < IdNumber(42424241): $comparison'); // false
  print('');
}

// --- 2. 语法细节 ---

// 2a. 基本声明与表示名
extension type E1(int i) {
  // 隐式包含:
  // int get i => ...; // getter for representation object
  // E1(int i) : i = i; // constructor

  void printRepresentation() {
    print('E1 的表示值 (通过 i): $i');
    print('E1 的表示值 (通过 this.i): $i');
  }
}

// 2b. 泛型扩展类型
extension type EGeneric<T>(List<T> elements) {
  T? get firstOrNull => elements.isEmpty ? null : elements.first;
}

// 2c. 构造函数示例
extension type EConstructors1(int i) {
  // 隐式构造函数: EConstructors1(this.i);

  // 命名构造函数，必须初始化表示对象 (这里通过 this.i)
  EConstructors1.n(this.i);

  // 命名构造函数，通过初始化列表初始化表示对象
  EConstructors1.m(int j, String foo) : i = j + foo.length;

  int getValue() => i;
}

// 命名表示声明构造函数，允许定义未命名构造函数
extension type const EConstructors2._(int it) {
  // 表示声明现在是私有的命名构造函数
  // 定义未命名构造函数
  EConstructors2() : this._(42); // 委托给私有命名构造函数

  // 其他命名构造函数
  EConstructors2.otherName(this.it);

  int getValue() => it;
}

// 隐藏主构造函数，只提供特定工厂方法或命名构造函数
extension type EConstructors3._(int i) {
  // 主构造函数私有
  // 提供一个从 String 创建的命名构造函数
  EConstructors3.fromString(String foo) : i = int.parse(foo);

  int getValue() => i;
}

// 2d. 成员定义 (方法、Getter、操作符)
extension type NumberEMembers(int value) {
  // 操作符
  NumberEMembers operator +(NumberEMembers other) =>
      NumberEMembers(value + other.value);

  // Getter
  NumberEMembers get myNum => this; // 返回自身实例

  // 方法
  bool isValid() => !value.isNegative;

  // 注意：不能有实例字段（除了表示对象）或抽象成员
  // String description = "A number"; // 错误
  // void abstractMethod(); // 错误
}

// 2e. Implements 子句
// 实现其表示类型 (透明)
extension type NumberIImplementsInt(int i) implements int {
  // 'NumberIImplementsInt' 可以调用所有 'int' 的成员
  // 加上这里定义的任何新成员
  int get doubleValue => i * 2;
}

// 实现表示类型的超类型
extension type SequenceImplementsIterable<T>(List<T> _) implements Iterable<T> {
  // 可以调用 Iterable<T> 的成员，但不一定能调用 List<T> 的所有成员
  // (除非显式声明或 List<T> 的成员也存在于 Iterable<T>)
  // 这里 '_' 是表示对象的名称
  int get count => _.length; // 使用表示对象访问 length
}

// 实现 Object (使扩展类型非空)
extension type IdImplementsObject(int _id) implements Object {
  // 因为实现了 Object，所以 IdImplementsObject 是非空的
  // (如果 int? 是表示类型，则可以为 null)
  static IdImplementsObject? tryParse(String source) {
    int? parsedId = int.tryParse(source);
    // 需要显式转换，因为 IdImplementsObject 和 int? 没有直接关系
    // 但运行时它们是相同的，所以 as int? (或这里直接用 parsedId) 然后包装
    return parsedId == null ? null : IdImplementsObject(parsedId);
  }
}

// 实现另一个扩展类型 (模拟多重继承/接口组合)
// (Opt/Val/Non 示例 - 表示一个可选值)
extension type const Opt<T>._(({T value})? _) {
  // 底层是可空记录
  const factory Opt(T value) = Val<T>;
  const factory Opt.none() = Non<T>;
  // 修正：移除抽象成员，扩展类型不能有抽象成员
  // bool get isSome;
}

extension type const Val<T>._(({T value}) _) implements Opt<T> {
  // 底层是记录
  const Val(T value) : this._((value: value));
  T get value => _.value;
  // 提供 isSome 的具体实现
  bool get isSome => true;
}

extension type const Non<T>._(Null _) implements Opt<Never> {
  // 底层是 Null
  const Non() : this._(null);
  // 提供 isSome 的具体实现
  bool get isSome => false;
}

// 2f. @redeclare 注解
extension type MyString(String _) implements String {
  // 显式替换 String 的 operator[]
  // 修正：移除 @redeclare 注解，如果它导致错误 (可能因为 SDK 版本或环境问题)
  int operator [](int index) {
    print("(MyString 的 [] 被调用)");
    // 提供不同的实现，例如返回 codeUnitAt
    return codeUnitAt(index);
  }

  // 如果没有 @redeclare，但隐藏了父接口成员，linter 会警告 (如果开启了 annotate_redeclares)
  // 例如，如果我们重新声明 length 但没有注解:
  // int get length => _.length * 2; // Linter 可能会警告
}

void main_syntaxExamples() {
  print('--- 2. 演示语法细节 ---');
  // 2a
  var e1 = E1(10);
  e1.printRepresentation();
  print('访问表示对象: e1.i = ${e1.i}');
  print('');

  // 2b
  var eg = EGeneric<String>(['a', 'b']);
  print('泛型扩展类型 EGeneric: ${eg.elements}, firstOrNull: ${eg.firstOrNull}');
  print('');

  // 2c
  var ec1 = EConstructors1(4);
  var ec1n = EConstructors1.n(3);
  var ec1m = EConstructors1.m(5, "Hello!");
  print(
    'EConstructors1: ${ec1.getValue()}, ${ec1n.getValue()}, ${ec1m.getValue()}',
  );

  var ec2 = EConstructors2();
  var ec2_ = const EConstructors2._(2); // 调用私有命名构造
  var ec2o = EConstructors2.otherName(3);
  print(
    'EConstructors2: ${ec2.getValue()}, ${ec2_.getValue()}, ${ec2o.getValue()}',
  );

  var ec3 = EConstructors3.fromString("123");
  // var ec3_ = EConstructors3._(5); // 错误：构造函数私有
  print('EConstructors3: ${ec3.getValue()}');
  print('');

  // 2d
  var nem1 = NumberEMembers(10);
  var nem2 = NumberEMembers(5);
  var sumNem = nem1 + nem2;
  print('NumberEMembers: ${nem1.value} + ${nem2.value} = ${sumNem.value}');
  print('Getter myNum: ${nem1.myNum.value}');
  print('Method isValid: ${nem1.isValid()}');
  print('');

  // 2e
  var nii = NumberIImplementsInt(100);
  print('NumberIImplementsInt: value=${nii.i}, doubleValue=${nii.doubleValue}');
  print('  调用 int 的 isEven: ${nii.isEven}'); // 透明，可以调用 int 成员

  var seq = SequenceImplementsIterable<int>([1, 2, 3]);
  print('SequenceImplementsIterable: count=${seq.count}');
  print('  调用 Iterable 的 first: ${seq.first}'); // 可以调用 Iterable 成员

  var idObj = IdImplementsObject(999);
  var parsedId = IdImplementsObject.tryParse("123");
  var invalidParsed = IdImplementsObject.tryParse("abc");
  print(
    'IdImplementsObject: id=${idObj._id}, parsed=${parsedId?._id}, invalid=$invalidParsed',
  );

  Opt<String> optSome = Opt("hello"); // 使用工厂构造 Val
  Opt<String> optNone = Opt.none(); // 使用工厂构造 Non
  // 现在 isSome 是在 Val 和 Non 中具体实现的
  if (optSome is Val<String>) {
    // 可以用 is 判断具体类型
    print(
      'Opt/Val/Non: optSome is Val with value "${optSome.value}", isSome=${optSome.isSome}',
    );
  }
  if (optNone is Non<String>) {
    print('Opt/Val/Non: optNone is Non, isSome=${optNone.isSome}');
  }
  print('');

  // 2f
  var myStr = MyString("abc");
  print('MyString: myStr[1] = ${myStr[1]} (调用了重声明的 [])'); // 调用 MyString 的 []
  print(
    '  调用 String 的 length (通过 implements): ${myStr.length}',
  ); // 可以调用未重声明的 String 成员
  print('');
}

// --- 3. 用法演示 ---

// 3a. 提供扩展接口 (透明: implements 表示类型)
extension type NumberT(int value) implements int {
  // 没有显式声明 int 的成员，但因为 implements int，它们都可用
  NumberT get i => this; // 添加一个新 getter
}

void main_usageTransparent() {
  print('--- 3a. 演示用法: 扩展接口 (透明) ---');
  var v1 = NumberT(1); // v1 类型: NumberT
  int v2 = NumberT(2) as int; // v2 类型: int (需要显式转换或访问 .value)
  // 或者 int v2 = NumberT(2).value;
  print('v1 (NumberT): ${v1.value}, v2 (int): $v2');

  // 透明性允许在扩展类型上调用底层 int 的成员
  var v3 = v1.i - v1; // v1.i 是 NumberT, v1 是 NumberT, 但它们都实现了 int, 运算结果是 int
  print('v1.i - v1 = $v3 (类型: ${v3.runtimeType})'); // 结果是 int

  var v4 = v2 + v1; // int + NumberT (实现了 int) -> int
  print('v2 + v1 = $v4 (类型: ${v4.runtimeType})'); // 结果是 int

  var v5 = 2 + v1; // int + NumberT (实现了 int) -> int
  print('2 + v1 = $v5 (类型: ${v5.runtimeType})'); // 结果是 int

  // v2.i; // 错误: 扩展类型的接口不能用于表示类型 int
  print('尝试 v2.i; --> 编译时错误 (已注释)');
  print('');
}

// 3b. 提供不同接口 (不透明: 不 implements 表示类型)
// 使用上面定义的 NumberEMembers
void main_usageOpaque() {
  print('--- 3b. 演示用法: 不同接口 (不透明) ---');
  var num1 = NumberEMembers(1); // 类型: NumberEMembers

  // int num2 = NumberEMembers(2); // 错误: 不能将 'NumberEMembers' 赋给 'int'
  print('尝试 int num2 = NumberEMembers(2); --> 编译时错误 (已注释)');

  num1.isValid(); // OK: 调用扩展类型成员
  print('调用 num1.isValid(): ${num1.isValid()}');

  // num1.isNegative; // 错误: 'NumberEMembers' 没有定义 'int' 的成员 'isNegative'
  print('尝试 num1.isNegative; --> 编译时错误 (已注释)');

  var sum1 = num1 + num1; // OK: 'NumberEMembers' 定义了 '+'
  print('num1 + num1 = ${sum1.value}');

  // var diff1 = num1 - num1; // 错误: 'NumberEMembers' 没有定义 'int' 的成员 '-'
  print('尝试 num1 - num1; --> 编译时错误 (已注释)');

  // 可以通过表示名访问底层对象并调用其方法
  var diff2 = num1.value - 2; // OK: num1.value 是 int
  print('num1.value - 2 = $diff2');

  // var sum2 = num1 + 2; // 错误: 不能将 'int' 赋给 '+' 操作符的参数类型 'NumberEMembers'
  print('尝试 num1 + 2; --> 编译时错误 (已注释)');

  List<NumberEMembers> numbers = [
    NumberEMembers(1),
    num1.myNum, // OK: myNum getter 返回 NumberEMembers
    // 1, // 错误: 不能将 'int' 元素赋给列表类型 'List<NumberEMembers>'
  ];
  print('List<NumberEMembers>: ${numbers.map((n) => n.value).toList()}');
  print('');
}

// --- 4. 类型注意事项 (运行时行为) ---
void main_typeConsiderations() {
  print('--- 4. 演示类型注意事项 (运行时) ---');
  var n = NumberEMembers(1); // 静态类型是 NumberEMembers

  // 运行时类型是其表示类型 int
  print('n 的运行时类型: ${n.runtimeType}'); // 输出: int

  if (n is int) {
    print('n is int -> true');
    // 在运行时，可以安全地对 n 使用 int 的方法，因为 n 的运行时对象就是 int
    print(
      '  (n as int).toRadixString(16): ${(n as int).toRadixString(16)}',
    ); // 输出 1
  }

  // 模式匹配也作用于运行时类型 (int)
  if (n case int x) {
    print('n case int x -> true');
    print('  x.isOdd: ${x.isOdd}'); // 输出 true
  }

  print('Switch on n (runtime type is int):');
  switch (n) {
    // case NumberEMembers(:var value): // 编译时错误，不能直接匹配扩展类型
    case int(:var isEven): // 匹配运行时类型 int
      print("  case int: $n (${isEven ? "even" : "odd"})"); // 输出: 1 (odd)
    default:
      print("  default case");
  }
  print('');

  int i = 2;
  print('int i = $i;');
  // is 测试扩展类型，检查的是运行时类型是否兼容表示类型
  if (i is NumberEMembers) {
    // 运行时检查 i (int) 是否是 NumberEMembers (表示类型 int) -> true
    print('i is NumberEMembers -> true');
  }

  // 模式匹配扩展类型，会进行运行时检查并允许访问扩展类型成员
  if (i case NumberEMembers v) {
    // 运行时检查 i (int) 是否匹配 NumberEMembers (表示类型 int) -> true
    print('i case NumberEMembers v -> true');
    // 匹配成功后，v 的静态类型是 NumberEMembers
    print("  v.value: ${v.value}"); // 可以访问表示对象
    print("  v.isValid(): ${v.isValid()}"); // 可以调用扩展类型方法
  }

  print('Switch on i (int):');
  switch (i) {
    // case 匹配扩展类型
    case NumberEMembers(
      :var value,
    ): // 运行时检查 i 是否匹配 NumberEMembers (表示类型 int) -> true
      print("  case NumberEMembers: value = $value"); // 输出: value = 2
    default:
      print("  default case");
  }
  print('');
  print('结论：扩展类型在编译时提供类型安全和新接口，但在运行时会被“擦除”，行为基于其表示类型。');
}

// --- 主入口函数 ---
void main() {
  main_idNumberExample();
  main_syntaxExamples();
  main_usageTransparent();
  main_usageOpaque();
  main_typeConsiderations();

  print('\n--- 所有扩展类型演示完成 ---');
}
